/************************************************************************/
// Copyright (C) 2016, han_gangbiao. All rights reserved.
// Use of this source code is governed by a GPL-v2 license that can be found in the License file.
// 
// [Time]:      2016-1-4 21:53:17
// [Author]:    han_gangbiao [http://my.oschina.net/jackhen]
// [Info]:      
/************************************************************************/

#include "net/net_reactor.h"
#include "protocol/net_binary_decoder.h"
#include "base/xthread.h"
#include <list>

std::list<int> g_list_conns;
net_reactor_t g_reactor_engine;

class TcpServer : public IEvent_handler, public IBinaryDecoderListener
{
public:
    TcpServer() : m_decoder(this) { }
    virtual ~TcpServer() { }
    
protected:
    virtual int on_connect( SOCK_FD listen_fd, SOCK_FD cli_fd, const char* remote_ip, int remote_port );
	virtual int on_data( SOCK_FD fd, const char* data, int len, const char* remote_ip, int remote_port );
	virtual int on_send_ack( SOCK_FD fd, int len );
	virtual int on_close( SOCK_FD fd, int error );
    
    virtual int onPDU( int fd, smart::ref_ptr<NetBinaryPdu> pdu );
	virtual int onError( int fd, BinaryDecoderError_t err );
private:
    NetBinaryDecoder m_decoder;
};

int TcpServer::on_connect( SOCK_FD listen_fd, SOCK_FD cli_fd, const char* remote_ip, int remote_port )
{
    printf("on_connect listen_fd=%d, cli_fd=%d, remote_ip[%s], remote_port[%d]\n", listen_fd, cli_fd, remote_ip, remote_port);
    g_list_conns.push_back(cli_fd);
    return 0;
}

int TcpServer::on_data( SOCK_FD fd, const char* data, int len, const char* remote_ip, int remote_port )
{
    //printf("on_data fd=%d, data=[%s], len=[%d], remote_ip[%s], remote_port[%d]\n", fd, data, len, remote_ip, remote_port);
    //g_reactor_engine.send(fd, data, len);
    m_decoder.Parse(fd, data, len);
    return 0;
}

int TcpServer::on_send_ack( SOCK_FD fd, int len )
{
    //printf("on_send_ack fd=%d, len=[%d]\n", fd, len);
    return 0;
}

int TcpServer::on_close( SOCK_FD fd, int error )
{
    printf("on_close fd=%d, error=%d\n", fd, error);
    return 0;
}

int TcpServer::onPDU( int fd, smart::ref_ptr<NetBinaryPdu> pdu )
{
//	printf("onPDU\n");
    pdu->toStream();
    g_reactor_engine.send(fd, pdu->getBinaryStream(), pdu->getBinaryStreamLength());
    return 0;
}

int TcpServer::onError( int fd, BinaryDecoderError_t err )
{
    printf("onError fd=%d, err=%d\n", fd, err);
    return 0;
}

char my_getch()
{
    char ch;
    ch = getchar();
    SLEEP_MS(100);
    return ch;
}

int main(int argc, char* argv[])
{
    TcpServer* tcpserver = new TcpServer();
    g_reactor_engine.init_reactor(tcpserver, 4);
    
    SOCK_FD listenfd = g_reactor_engine.open_tcp_server("0.0.0.0", 8800);
    if(listenfd > 0)
    {
        printf("start tcpserver listen at[0.0.0.0:8800], listenfd=%d\n", listenfd);
    }
    else
    {
        printf("tcpserver failed listen at[0.0.0.0:8800]\n");
    }
    
    char c;
    do {
        c = my_getch();
        printf("Press q or Q to exit...\n");
    } while(c!='q' && c!='Q');
    
    g_reactor_engine.close_fd(listenfd);
    g_reactor_engine.uninit_reactor();
    SAFE_DELETE(tcpserver);
    return 0;
}
